<template>
  <view class="fu-code-input">
    <!-- 真实输入框(隐藏) -->
    <input
      class="fu-code-input__field"
      :type="type"
      :value="value"
      :maxlength="length"
      :focus="isFocus"
      :disabled="disabled"
      :adjust-position="false"
      @input="onInput"
      @focus="onFocus"
      @blur="onBlur"
    />
    
    <!-- 显示框 -->
    <view 
      class="fu-code-input__box"
      :class="[
        `fu-code-input__box--${mode}`,
        { 'is-focused': focused }
      ]"
      @tap="handleTap"
    >
      <view 
        v-for="(item, index) in codeArray"
        :key="index"
        class="fu-code-input__item"
        :class="{ 'is-active': focused && cursorIndex === index }"
      >
        <text v-if="item" class="fu-code-input__char">
          {{ mask ? '•' : item }}
        </text>
        <view 
          v-if="focused && cursorIndex === index" 
          class="fu-code-input__cursor"
        ></view>
      </view>
    </view>
  </view>
</template>

<script>
/**
 * @description 验证码输入组件
 * @property {String} value/v-model 输入值
 * @property {Number} length 验证码长度
 * @property {Boolean} focus 是否自动聚焦
 * @property {Boolean} mask 是否启用密码模式
 * @property {String} mode 显示模式，可选值：box/underline
 * @property {String} type 输入类型，可选值：text/number
 * @property {Boolean} disabled 是否禁用
 * @event {Function} input 输入时触发
 * @event {Function} complete 输入完成时触发
 */
export default {
  name: 'FuCodeInput',
  
  props: {
    // v-model值
    value: {
      type: String,
      default: ''
    },
    // 验证码长度
    length: {
      type: Number,
      default: 4
    },
    // 是否自动聚焦
    focus: {
      type: Boolean,
      default: false
    },
    // 是否启用密码模式
    mask: {
      type: Boolean,
      default: false
    },
    // 显示模式
    mode: {
      type: String,
      default: 'box', // box/underline
      validator: val => ['box', 'underline'].includes(val)
    },
    // 输入类型
    type: {
      type: String,
      default: 'text', // text/number
      validator: val => ['text', 'number'].includes(val)
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    }
  },
  
  data() {
    return {
      focused: false,
      cursorIndex: 0,
      isFocus: false,
      inputValue: ''
    }
  },
  
  watch: {
    // 监听外部值变化
    value: {
      handler(val) {
        this.inputValue = val
      },
      immediate: true
    },
    
    // 监听外部 focus 属性变化
    focus: {
      handler(val) {
        this.isFocus = val
      },
      immediate: true
    }
  },
  
  computed: {
    codeArray() {
      return Array(this.length).fill('').map((_, i) => this.inputValue[i] || '')
    }
  },
  
  methods: {
    // 处理输入
    onInput(e) {
      const value = e.detail.value.slice(0, this.length)
      
      // 只允许输入数字
      if (this.type === 'number' && !/^\d*$/.test(value)) {
        this.inputValue = this.value
        return
      }
      
      this.inputValue = value
      this.$emit('input', value)
      
      // 输入完成时触发
      if (value.length === this.length) {
        this.$emit('complete', value)
      }
      
      // 更新光标位置
      this.cursorIndex = value.length
    },
    
    // 处理点击
    handleTap() {
      if (!this.disabled) {
        this.isFocus = true
      }
    },
    
    // 处理聚焦
    onFocus() {
      this.focused = true
      this.cursorIndex = this.value.length
      this.$emit('focus')
    },
    
    // 处理失焦
    onBlur() {
      this.focused = false
      this.isFocus = false
      this.$emit('blur')
    }
  }
}
</script>

<style lang="scss">
.fu-code-input {
  position: relative;
  
  &__field {
    position: absolute;
    top: 0;
    left: -100%;
    width: 0;
    height: 0;
    opacity: 0;
    z-index: -1;
  }
  
  &__box {
    display: flex;
    justify-content: space-between;
    align-items: center;
    
    &--box {
      .fu-code-input__item {
        width: 100rpx;
        height: 100rpx;
        border: 2rpx solid #dcdfe6;
        border-radius: 8rpx;
        
        &.is-active {
          border-color: #2979ff;
        }
      }
    }
    
    &--underline {
      .fu-code-input__item {
        width: 80rpx;
        height: 80rpx;
        border-bottom: 4rpx solid #dcdfe6;
        
        &.is-active {
          border-color: #2979ff;
        }
      }
    }
  }
  
  &__item {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s;
  }
  
  &__char {
    font-size: 36rpx;
    color: #303133;
  }
  
  &__cursor {
    position: absolute;
    width: 2rpx;
    height: 40rpx;
    background: #2979ff;
    animation: cursor 1s infinite;
  }
}

@keyframes cursor {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}
</style> 